<?php

class Helper_L18n
{

	protected $_translate = null;

	public function __construct()
	{
		/**
		 *
		 */
		require_once 'Zend/Translate.php';

	}

	public function getTranslate()
	{
		if (null == $this -> _translate)
		{
			// Set cache
			$cache = Agis::getHelper('@cache') -> getCache('core');

			if ($cache)
			{
				// Zend_Translate::setCache($cache);
			}

			// If in development, log untranslated messages
			$params = array(
					'scan' => Zend_Translate_Adapter::LOCALE_FILENAME,
					'logUntranslated' => false
			);

			// Main
			$this -> _translate = new Zend_Translate('Csv', APP_PATH . '/translate/', null, $params);

		}
		return $this -> _translate;
	}

	/**
	 * translate
	 */
	public function _($messageid = null)
	{
		if ($messageid === null)
		{
			return null;
		}

		$translate = $this -> getTranslate();
		$options = func_get_args();

		array_shift($options);
		$count = count($options);
		$locale = null;
		if ($count > 0)
		{
			if (Zend_Locale::isLocale($options[($count - 1)], null, false) !== false)
			{
				$locale = array_pop($options);
			}
		}

		if ((count($options) === 1) and (is_array($options[0]) === true))
		{
			$options = $options[0];
		}

		if ($translate !== null)
		{
			$messageid = $translate -> translate($messageid, $locale);
		}

		if (count($options) === 0)
		{
			return $messageid;
		}

		return vsprintf($messageid, $options);
	}

	protected $_locale = null;

	/**
	 * Set the current locale
	 *
	 * @param string|Zend_Locale $locale
	 * @return Engine_View_Helper_Locale
	 */
	public function setLocale($locale)
	{
		if (is_string($locale))
		{
			$locale = new Zend_Locale($locale);
		}

		if (!$locale instanceof Zend_Locale)
		{
			throw new Exception('Not passed locale object or valid locale string');
		}

		$this -> _locale = $locale;
		return $this;
	}

	/**
	 * Get the current locale. Defaults to locale in registry
	 *
	 * @return Zend_Locale
	 */
	public function getLocale()
	{
		if (null === $this -> _locale)
		{
			$this -> _locale = Agis::get('locale');
		}

		return $this -> _locale;
	}

	public function getTimezone()
	{
		return Agis::get('timezone');
	}

	/**
	 * Format a number according to locale and currency
	 * @param  integer|float  $number
	 * @return string
	 * @see Zend_Currency::toCurrency()
	 */
	public function toCurrency($value, $currency, $options = array())
	{
		$options = array_merge(array(
				'locale' => $this -> getLocale(),
				'display' => 2,
				'precision' => 2,
		), $options);

		// Doesn't like locales w/o regions
		if (is_object($options['locale']))
		{
			$locale = $options['locale'] -> __toString();
		}
		else
		{
			$locale = (string)$options['locale'];
		}
		if (strlen($locale) < 5)
		{
			$locale = Zend_Locale::getBrowser();
			if (is_array($locale))
			{
				foreach ($locale as $browserLocale => $q)
				{
					if (strlen($browserLocale) >= 5)
					{
						$locale = $browserLocale;
						break;
					}
				}
			}
			if (!$locale || !is_string($locale) || strlen($locale) < 5)
			{
				$locale = 'en_US';
			}
		}
		unset($options['locale']);

		$currency = new Zend_Currency($currency, $locale);

		return $currency -> toCurrency($value, $options);
	}

	/**
	 * Format a number according to locale
	 * @param mixed $number
	 * @see Zend_Locale_Format::toNumber()
	 */
	public function toNumber($number, $options = array())
	{
		$options = array_merge(array('locale' => $this -> getLocale()), $options);

		// Convert numerals?
		$convert = false;
		if (!isset($options['convert']) || $options['convert'])
		{
			$convert = true;
			unset($options['convert']);
		}

		// Format
		$number = Zend_Locale_Format::toNumber($number, $options);

		// Convert numerals
		if ($convert)
		{
			$number = $this -> convertNumerals($number, $options['locale']);
		}

		return $number;
	}

	public function toTime($date, $options = array())
	{
		$options = array_merge(array(
				'locale' => $this -> getLocale(),
				'size' => 'short',
				'type' => 'time',
				'timezone' => Agis::get('timezone'),
		), $options);

		$date = $this -> _checkDateTime($date, $options);
		if (!$date)
		{
			return false;
		}

		if (empty($options['format']))
		{
			$options['format'] = Zend_Locale_Data::getContent($options['locale'], $options['type'], $options['size']);
		}
		// Hack for weird usage of L instead of M in Zend_Locale
		$options['format'] = str_replace('L', 'M', $options['format']);

		$str = $date -> toString($options['format'], $options['locale']);
		$str = $this -> convertNumerals($str, $options['locale']);
		return $str;
	}

	public function toDate($date, $options = array())
	{
		$options = array_merge(array(
				'locale' => $this -> getLocale(),
				'size' => 'short',
				'type' => 'date',
				'timezone' => Agis::get('timezone'),
		), $options);

		$date = $this -> _checkDateTime($date, $options);
		if (!$date)
		{
			return false;
		}

		if (empty($options['format']))
		{
			$options['format'] = Zend_Locale_Data::getContent($options['locale'], $options['type'], $options['size']);
		}
		// Hack for weird usage of L instead of M in Zend_Locale
		$options['format'] = str_replace('L', 'M', $options['format']);

		$str = $date -> toString($options['format'], $options['locale']);
		$str = $this -> convertNumerals($str, $options['locale']);
		return $str;
	}

	public function toDateTime($date, $options = array())
	{
		$options = array_merge(array(
				'locale' => $this -> getLocale(),
				'size' => 'long',
				'type' => 'datetime',
				'timezone' => Agis::get('timezone'),
		), $options);

		$date = $this -> _checkDateTime($date, $options);
		if (!$date)
		{
			return false;
		}

		if (empty($options['format']))
		{
			$options['format'] = Zend_Locale_Data::getContent($options['locale'], $options['type'], $options['size']);
		}
		// Hack for weird usage of L instead of M in Zend_Locale
		$options['format'] = str_replace('L', 'M', $options['format']);

		$str = $date -> toString($options['format'], $options['locale']);
		$str = $this -> convertNumerals($str, $options['locale']);
		return $str;
	}

	protected function _checkDateTime($datetime, $options = array())
	{
		if (is_numeric($datetime))
		{
			$datetime = new Zend_Date($datetime);
		}
		else
		if (is_string($datetime))
		{
			$datetime = new Zend_Date(strtotime($datetime));
		}
		else
		if (!($datetime instanceof Zend_Date))
		{
			return false;
		}

		if (!($datetime instanceof Zend_Date))
		{
			throw new Exception('Not a valid date');
		}

		if (!isset($options['timezone']) && Agis::get('timezone'))
		{
			$options['timezone'] = Agis::get('timezone');
		}

		if (!isset($options['locale']))
		{
			$options['locale'] = $this -> getLocale();
		}

		if ($options['timezone'])
		{
			$datetime -> setTimezone($options['timezone']);
		}

		if ($options['locale'])
		{
			$datetime -> setLocale($options['locale']);
		}

		return $datetime;
	}

	public function convertNumerals($string, $locale = null)
	{
		if (!$locale)
		{
			$locale = $this -> getLocale();
		}

		// Get the numbering system
		$defaultNumberingSystem = null;
		try
		{
			$defaultNumberingSystem = Zend_Locale_Data::getContent($locale, 'defaultnumberingsystem');
		}
		catch( Exception $e )
		{
			// Silence
		}

		// Convert now
		if ($defaultNumberingSystem && 'latn' != strtolower($defaultNumberingSystem))
		{
			$string = Zend_Locale_Format::convertNumerals($string, 'Latn', $defaultNumberingSystem);
		}

		return $string;
	}

}
